/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.bff.designtime.generator.core.querycondition;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.inspur.edp.bff.designtime.generator.core.VmCoreGenContext;
import com.inspur.edp.caf.generator.baseInfo.ParameterInfo;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.cef.api.message.CefException;
import com.inspur.edp.cef.entity.condition.FilterCondition;
import com.inspur.edp.cef.generator.overall.GeneratorUtil;
import org.eclipse.jdt.core.dom.*;
import org.eclipse.jdt.core.dom.Assignment.Operator;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;

import java.util.ArrayList;
import java.util.Arrays;

public class VMDefalutFilterConditionGenereator extends ClassMethodGenerator {
  private VmCoreGenContext coreGenContext;
  private java.lang.String methodname="getDefaultFilterCondition";
  public VMDefalutFilterConditionGenereator(VmCoreGenContext coreGenContext){
    this.coreGenContext=coreGenContext;
  }

  @Override
  protected Block buildMethodBody() {
    Block block=ast.newBlock();
    java.lang.String serializer=coreGenContext.getVmGenContext().getVm().getMainObject().getFilterCondition();
    if(serializer==null||serializer.equals("")){
      NullLiteral nullLiteral=ast.newNullLiteral();
      ReturnStatement returnStatement1=ast.newReturnStatement();
      returnStatement1.setExpression(nullLiteral);
      block.statements().add(returnStatement1);
      return block;
    }
    getVarStatement(ast,serializer,block);
    getVarClassInstanceStatement(ast,block);
    getMapperStatement(ast,block);
    getTryStatement(ast,block);
    getReturnStatement(ast,block);
    return block;
  }

  private void getVarStatement(AST ast, String serializer,Block block){
    StringLiteral stringLiteral=ast.newStringLiteral();
    stringLiteral.setLiteralValue(serializer);
    VariableDeclarationFragment varFragment=ast.newVariableDeclarationFragment();
    varFragment.setInitializer(stringLiteral);
    varFragment.setName(ast.newSimpleName("filterCondition"));
    VariableDeclarationStatement varstatement=ast.newVariableDeclarationStatement(varFragment);
    varstatement.setType(ast.newSimpleType((ast.newSimpleName("String"))));
    block.statements().add(varstatement);
  }
  private void getVarClassInstanceStatement(AST ast,Block block){
    ParameterizedType paraType=ast.newParameterizedType(ast.newSimpleType(ast.newName(ArrayList.class.getTypeName())));

    paraType.typeArguments().add(ast.newSimpleType(ast.newName(FilterCondition.class.getTypeName())));

    VariableDeclarationFragment varFragment=ast.newVariableDeclarationFragment();
    varFragment.setName(ast.newSimpleName("filterConditions"));
    ClassInstanceCreation instance=ast.newClassInstanceCreation();
    ParameterizedType type=ast.newParameterizedType(ast.newSimpleType(ast.newName(ArrayList.class.getTypeName())));
    instance.setType(type);
    varFragment.setInitializer(instance);
    VariableDeclarationStatement varstatement=ast.newVariableDeclarationStatement(varFragment);
    varstatement.setType(paraType);
    block.statements().add(varstatement);
  }
  private void getMapperStatement(AST ast,Block block){
    VariableDeclarationFragment varFragment=ast.newVariableDeclarationFragment();
    varFragment.setName(ast.newSimpleName("mapper"));
    ClassInstanceCreation instance=ast.newClassInstanceCreation();
    instance.setType(new TypeInfo(ObjectMapper.class).getType(ast,coreGenContext));

    varFragment.setInitializer(instance);
    VariableDeclarationStatement varstatement=ast.newVariableDeclarationStatement(varFragment);
    varstatement.setType(ast.newSimpleType(ast.newSimpleName(ObjectMapper.class.getSimpleName())));
    addImport(ObjectMapper.class.getTypeName());
    block.statements().add(varstatement);
  }
  private  void getReturnStatement(AST ast,Block block){
    ReturnStatement statement=ast.newReturnStatement();
    statement.setExpression(ast.newSimpleName("filterConditions"));
    block.statements().add(statement);
  }
  private void getTryStatement(AST ast,Block block){
    TryStatement statement=ast.newTryStatement();
    Block block1=ast.newBlock();
    Assignment assignment=ast.newAssignment();
    assignment.setLeftHandSide(ast.newSimpleName("filterConditions"));
    assignment.setOperator(Operator.ASSIGN);
    MethodInvocation method=ast.newMethodInvocation();
    method.setExpression(ast.newSimpleName("mapper"));
    method.setName(ast.newSimpleName("readValue"));

    ClassInstanceCreation creation=ast.newClassInstanceCreation();

    ParameterizedType type=ast.newParameterizedType(ast.newSimpleType(ast.newName(TypeReference.class.getTypeName())));

    ParameterizedType type1=ast.newParameterizedType(ast.newSimpleType(ast.newName(ArrayList.class.getTypeName())));
    type1.typeArguments().add(new TypeInfo(FilterCondition.class).getType(ast, coreGenContext));

    type.typeArguments().add(type1);
    creation.setType(type);
    creation.setAnonymousClassDeclaration(ast.newAnonymousClassDeclaration());
    method.arguments().add(ast.newSimpleName("filterCondition"));
    method.arguments().add(creation);
    assignment.setRightHandSide(method);
    ExpressionStatement expression =ast.newExpressionStatement(assignment);
    block1.statements().add(expression);

    CatchClause catchClause=ast.newCatchClause();
    Block block2=ast.newBlock();
    SingleVariableDeclaration singleVar=ast.newSingleVariableDeclaration();
    singleVar.setType(ast.newSimpleType(ast.newName(JsonProcessingException.class.getTypeName())));
    singleVar.setName(ast.newSimpleName("e"));
    catchClause.setException(singleVar);
    addImport(CefException.class.getTypeName());
    ThrowStatement throwStatement= GeneratorUtil.getThrowStatementWithMessage(ast,"过滤条件反序列化失败！");
//    ClassInstanceCreation creation1=ast.newClassInstanceCreation();
//    creation1.setType(ast.newSimpleType(ast.newName(RuntimeException.class.getTypeName())));
//
//    StringLiteral stringLiteral=ast.newStringLiteral();
//    stringLiteral.setLiteralValue("过滤条件反序列化失败！");
//    creation1.arguments().add(stringLiteral);
//
//    throwStatement.setExpression(creation1);
    block2.statements().add(throwStatement);
    catchClause.setBody(block2);
    statement.catchClauses().add(catchClause);
    statement.setBody(block1);
    block.statements().add(statement);
  }
  @Override
  protected java.lang.String getMethodName() {
    return methodname;
  }

  @Override
  protected TypeInfo getReturnType() {
    TypeInfo result = new TypeInfo(ArrayList.class);
    result.setIsParameterizedType(true);
    result.setArguments(new ArrayList<TypeInfo>(
        Arrays.asList(new TypeInfo[]{new TypeInfo(FilterCondition.class)})));
    addImport(FilterCondition.class.getTypeName());
    return result;
  }

  @Override
  protected ArrayList<ModifierKeyword> getAccessModifiers() {
    return new java.util.ArrayList<Modifier.ModifierKeyword>(
        java.util.Arrays.asList(new Modifier.ModifierKeyword[]{ModifierKeyword.PUBLIC_KEYWORD}));
  }

  @Override
  protected ArrayList<ParameterInfo> getParameterCollection() {
    return null;
  }
}
